import {
  Injectable,
  HttpStatus,
  HttpException,
  UnauthorizedException,
} from '@nestjs/common';
import * as bcrypt from 'bcrypt';
import { UserService } from '../user/user.service';
import { JwtService } from '@nestjs/jwt';
import { Prisma } from '@prisma/client';
import { PrismaService } from '../common/services/prisma.service';
import { SignInDto } from './dto/auth.dto';

@Injectable()
export class AuthService {
  constructor(
    private userService: UserService,
    private jwtService: JwtService,
    private readonly prisma: PrismaService,
  ) {}

  async login(userInfo: SignInDto): Promise<any> {
    // mode登陆方式 1.用户名+密码 2手机+验证码 3微信登陆'
    const { mode } = userInfo;
    let res = null;
    switch (mode) {
      case '1':
        res = await this.loginWithUsernameAndPassword(userInfo);
        break;
      case '2':
        res = await this.loginWithPhoneAndCode(userInfo);
        break;
      case '3':
        res = await this.loginWithWeChat(userInfo);
        break;
    }

    if (res) {
      const payload = {
        mode,
        id: res.id,
        telphone: res.telphone,
        username: res.username,
        openid: res.openid,
      };
      return {
        access_token: await this.jwtService.signAsync(payload),
      };
    }
    throw new HttpException(
      {
        code: HttpStatus.BAD_REQUEST,
        data: '',
        message: '无效的用户信息，请检查',
      },
      HttpStatus.OK,
    );
  }

  // 手机+验证码登录逻辑
  async loginWithPhoneAndCode(userInfo) {
    const { telphone, validate_code } = userInfo;

    // TODO: 验证手机验证码逻辑
    if (validate_code !== '123456') {
      throw new HttpException(
        {
          code: HttpStatus.BAD_REQUEST,
          data: '',
          message: '验证码错误',
        },
        HttpStatus.OK,
      );
    }

    // 假设验证通过，从数据库获取用户信息
    const res = await this.prisma.user.findUnique({ where: { telphone } });
    if (!res) {
      throw new HttpException(
        {
          code: HttpStatus.BAD_REQUEST,
          data: '',
          message: '无法找到该手机号',
        },
        HttpStatus.OK,
      );
    }
    return res;
  }

  // 用户名(邮箱、手机号)+密码登录逻辑
  async loginWithUsernameAndPassword(userInfo) {
    const { username, password } = userInfo;

    // TODO 假如用户名是手机号或邮箱
    const res = await this.prisma.user.findUnique({
      where: {
        username,
      },
    });
    if (res === null || !bcrypt.compareSync(password, res.password_hash)) {
      throw new HttpException(
        {
          code: HttpStatus.BAD_REQUEST,
          data: '',
          message: '用户名或密码错误',
        },
        HttpStatus.OK,
      );
    }

    return res;
  }

  // 微信扫码登录逻辑（需要第三方服务集成）
  // 这里只是伪代码，你需要实现与微信开放平台的通信
  async loginWithWeChat(userInfo) {
    console.log('-loginWithWeChat--', userInfo);
    // TODO: 实现与微信开放平台的OAuth流程
    // ...
    // 假设你从微信服务器获取了用户信息并验证了其身份
    // 从数据库获取或创建用户信息
    // ...
    // 生成JWT或其他Token
    // ...
    return { token: 'your-jwt-token' };
  }

  async register(signupRequest: any): Promise<void> {
    const { password, ...rest } = signupRequest;
    try {
      await this.prisma.user.create({
        data: {
          ...rest,
          password_hash: await bcrypt.hash(password, 10),
        },
      });
    } catch (e) {
      const { code, meta = {} } = e;
      // 捕获数据库错误
      if (
        e instanceof Prisma.PrismaClientKnownRequestError &&
        code === 'P2002'
      ) {
        if (meta?.target?.indexOf('username') > -1) {
          throw new HttpException('用户名已存在', HttpStatus.BAD_REQUEST);
        }
        if (meta?.target?.indexOf('telephone') > -1) {
          throw new HttpException('电话已存在', HttpStatus.BAD_REQUEST);
        }
        if (meta?.target?.indexOf('email') > -1) {
          throw new HttpException('邮箱已存在', HttpStatus.BAD_REQUEST);
        }
      }
      throw new Error(e);
    }
  }

  async validateUser(payload: any): Promise<any> {
    const { id, username } = payload;
    console.log('userInfo---', payload);
    const res = await this.prisma.user.findUnique({
      where: { id },
    });
    console.log('res---', res);
    if (res !== null && res.username === username) {
      return res;
    }
    throw new UnauthorizedException();
  }
}
